package gradle.common.core.utils;

import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Json工具类
 */
@Slf4j
public class JsonUtil {

    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    static {
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 解决Java8新日期API序列化问题
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
        OBJECT_MAPPER.registerModule(javaTimeModule);
        OBJECT_MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    }

    public static final String NULL_STRING = "null";

    /**
     * 转换Json字符串 <br/>
     * 1. 入参为 null --> 返回 null <br/>
     * 2. 入参为 String --> 返回入参 <br/>
     * 3. 转化异常 --> 返回 null
     *
     * @param object 转换对象
     * @return Json字符串
     */
    public static String toJsonString(Object object) {
        if (object == null) {
            return null;
        }
        if (object.getClass() == String.class) {
            return (String) object;
        }
        try {
            return OBJECT_MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            log.error("【Json转换】序列化异常，异常信息: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 将实Json字符串转换为实体 <br/>
     * 1. 入参为 null --> 返回 null <br/>
     * 2. 入参为 "null"（不区分大小写）-->  返回 nul l<br/>
     * 3. 入参为 ""（空字符串）-->  返回 nul l<br/>
     *
     * @param text  Json字符串
     * @param clazz 返回实体
     * @param <T>   返回实体泛型
     * @return 转换后的实体
     */
    public static <T> T parseObject(String text, Class<T> clazz) {
        if (StringUtils.isBlank(text) || NULL_STRING.equals(text.toLowerCase())) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(text, clazz);
        } catch (JsonProcessingException e) {
            Matcher matcher = Pattern.compile("\\n\\s*").matcher(text);
            String filterBody = matcher.replaceAll("");
            log.error("【Json转换】反序列化异常，请求参数: {}, 异常信息: {}", filterBody, e.getMessage(), e);
            return null;
        }
    }


    /**
     * 将实Json字符串转换为实体 <br/>
     * 1. 入参为 null --> 返回 null <br/>
     * 2. 入参为 "null"（不区分大小写）-->  返回 nul l<br/>
     * 3. 入参为 ""（空字符串）-->  返回 nul l<br/>
     *
     * @param clazz 返回实体
     * @param <T>   返回实体泛型
     * @return 转换后的实体
     */
    public static <T> T parseObject(File file, Class<T> clazz) {
        try {
            if (file == null || clazz == null) {
                return null;
            }
            return OBJECT_MAPPER.readValue(file, clazz);
        } catch (Exception e) {
            log.error("【Json转换】反序列化异常, 异常信息: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 将实Json字符串转换为List <br/>
     * 1. 入参为 null --> 返回 null <br/>
     * 2. 入参为 "null"（不区分大小写）-->  返回 nul l<br/>
     * 3. 入参为 ""（空字符串）-->  返回 nul l<br/>
     *
     * @param text  Json字符串
     * @param clazz 返回List泛型
     * @param <E>   返回List泛型
     * @return 转换后的List
     */
    public static <E> List<E> parseArray(String text, Class<E> clazz) {
        if (StringUtils.isBlank(text) || NULL_STRING.equals(text.toLowerCase())) {
            return null;
        }
        try {
            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, clazz));
        } catch (JsonProcessingException e) {
            Matcher matcher = Pattern.compile("\\n\\s*").matcher(text);
            String filterBody = matcher.replaceAll("");
            log.error("【Json转换】反序列化异常，请求参数: {}, 异常信息: {}", filterBody, e.getMessage(), e);
            return null;
        }
    }


    /**
     * 获取JSON串指定Key的Value值
     *
     * @param text JSON
     * @param key  Key
     * @return key对应的value
     */
    public static String getString(@NotNull String text, @NotNull String key) {
        try {
            JsonNode rootNode = OBJECT_MAPPER.readTree(text);
            Iterator<Map.Entry<String, JsonNode>> elements = rootNode.fields();
            String elementValue = null;
            while (elements.hasNext()) {
                Map.Entry<String, JsonNode> next = elements.next();
                if (Objects.equals(key, next.getKey())) {
                    elementValue = next.getValue().toString();
                    break;
                }
            }
            return elementValue;
        } catch (JsonProcessingException e) {
            log.error("【JSON转换】解析JSON异常，请求参数 = {}, 异常信息: {}", text, e.getMessage(), e);
            return null;
        }
    }

    public static Object getJsonValue(String key, String json) {
        if (StringUtils.isBlank(key)) {
            return new Object();
        }
        HashMap<?, ?> jsonContent = JsonUtil.parseObject(json, HashMap.class);
        if (jsonContent != null && !jsonContent.isEmpty()) {
            for (Object contentKey : jsonContent.keySet()) {
                if (contentKey.toString().equals(key)) {
                    return jsonContent.get(key);
                }
            }
        }
        return new Object();
    }

    /**
     * 对象转Map
     *
     * @param object
     * @return
     * @throws IllegalAccessException
     */
    public static Map beanToMap(Object object) throws IllegalAccessException {
        Map<String, Object> map = new HashMap<String, Object>(16);
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            map.put(field.getName(), field.get(object));
        }
        return map;
    }


}
